! function(g, doc) {
    vue_config(Vue);
    doc.body.addEventListener('transitionend', initilization);
    var HEIGHT = 40;
    var WIDTH = 20;
    var SPEED_MIN = 300;
    var BLOCK_MAX_LENGTH = 4;
    var FRACTION_BEGIN = 100;

    var block, user;
    var isInit = false;

    function initilization() {
        if (isInit === true) {
            return;
        }
        isInit = true;
        var data = {
            gameLoading: true,
            scheduleText: '正在加载一些有的没的...',
            userData: [{}, {}],
            list: []
        };

        block = new Block(data);
        block.initBody();

        user = new User(block, data.userData[0]);

        new Vue({
            el: 'body',
            data: data,
            methods: {
                onTouchStart: function(evt) {
                    user.handle(evt);
                },
                onTouchEnd: function(evt) {
                    user.handle(evt);
                },
                action: function(evt) {
                    user.action(evt);
                }
            }
        });

        loop(0);

        //临时
        setTimeout(function() {
            data.gameLoading = false;
        }, 1000);
    }

    function vue_config(v) {
        vf = v.config;
        vf.debug = true;
        vf.silent = true;
    }

    function loop(timeGo) {
        user.update(timeGo);
        block.update(timeGo);
        g.requestAnimationFrame(loop);
    }

    function Block(data) {
        this.list = data.list; //绑定数据

        this.block = [
            [
                [
                    [0, 0, 0, 0],
                    [1, 1, 1, 1],
                    [0, 0, 0, 0],
                    [0, 0, 0, 0]
                ]
            ],
            [
                [
                    [1, 1],
                    [1, 1]
                ]
            ],
            [
                [
                    [0, 0, 1],
                    [1, 1, 1],
                    [0, 0, 0]
                ]
            ],
            [
                [
                    [1, 0, 0],
                    [1, 1, 1],
                    [0, 0, 0]
                ]
            ],
            [
                [
                    [0, 1, 1],
                    [1, 1, 0],
                    [0, 0, 0]
                ]
            ],
            [
                [
                    [1, 1, 0],
                    [0, 1, 1],
                    [0, 0, 0]
                ]
            ],
            [
                [
                    [0, 1, 0],
                    [1, 1, 1],
                    [0, 0, 0]
                ]
            ]
        ];
        //遍历各个方块
        for (var b = 0, len = this.block.length; b < len; b++) {
            var blk = this.block[b];
            //旋转4次
            for (var i = 0; i < 4; i++) {
                blk.push(this.rotation(blk[i]));
            }
        }
    }

    Block.prototype.rotation = function(arr) { //旋转二维数组//顺时针
        var result = [];
        var len = arr.length - 1;
        for (var i = 0; i <= len; i++) { //复制数组
            result.push(arr[i].slice(0));
        }

        for (var i = 0; i <= len; i++) {
            for (var j = 0; j <= len; j++) {
                result[i][j] = arr[j][len - i];
            }
        }
        return result;
    };

    Block.prototype.initBody = function() {
        for (var h = 0; h < HEIGHT; h++) {
            var arr = [];
            for (var w = 0; w < WIDTH; w++) {
                arr.push(this.getBlockData(h, w));
            }
            this.list.push(arr);
        }
    };

    Block.prototype.newLine = function() {
        var arr = [];
        for (var w = 0; w < WIDTH; w++) {
            arr.push(this.getBlockData(0, w));
        }
        return arr;
    };

    Block.prototype.getBlockData = function(h, w) {
        return {
            style: {
                //'box-shadow': 'inset 0 0 .1rem #fff'
            },
            h: h,
            w: w,
            filling: false
        };
    };

    Block.prototype.randomOne = function() {
        var count = this.block.length;
        var shape = Math.floor(Math.random() * count); //形状
        var len = this.block[shape].length;
        var direction = Math.floor(Math.random() * len); //方向
        return {
            block: this.block[shape],
            direction: direction
        };
    };

    Block.prototype.checkRepeat = function(block, isSet) {
        var length = block.block.length;
        var b;
        for (var i = 0; i < length; i++) {
            for (var j = 0; j < length; j++) {
                var height = j + block.y;
                var width = i + block.x;
                if(height < 0){
                    continue;
                }
                if (isSet === true) {
                    if (block.block[i][j] === 1) {
                        b = this.list[height][width];
                        b.filling = true;
                        b.style = block.style;
                    }
                } else if (isSet === false) {
                    if (block.block[i][j] === 1) {
                        b = this.list[height][width];
                        b.filling = false;
                        b.style = {};
                    }
                } else if (block.block[i][j] === 1) {
                    if (height >= HEIGHT || width < 0 || width >= WIDTH || this.list[height][width].filling === true) {
                        return true;
                    }
                }
            }
        }
        return false;
    };

    Block.prototype.checkDelete = function(callback) {
        var del = 0;
        for (var i = this.list.length - 1; i >= 0; i--) {
            var len = 0;
            for (var j = this.list[i].length - 1; j >= 0; j--) {
                if (this.list[i][j].filling === true) {
                    len++;
                }
            }
            if (len === WIDTH) {
                del++;
                for (var k = i; k > 0; k--) {
                    this.list.$set(k, this.list[k - 1]);
                }
                this.list.$set(0, this.newLine());
            }
        }
        callback(del);
    };

    Block.prototype.update = function(timeGo) {

    };

    function User(block, data) {
        this.data = data;
        data.line = 0;
        data.fraction = FRACTION_BEGIN;
        data.number = 0;
        data.style = {
            'box-shadow': '0 0 10px #00D6A5'
        }; //后期可作为皮肤等balabala

        this.block = block;
        this.handleBegin = false; //记录用户操作开始点
        this.actionWidth = Math.floor(doc.body.clientWidth / 10);
        this.actionHeight = Math.floor(doc.body.clientHeight / 15);

        this.updateLock = false;
        this.isGameOver = false;
        this.myBlock = this.getBlock(); //用户控制的方块
    }

    User.prototype.getBlock = function() {
        var b = this.block.randomOne();
        var block = {
            x: Math.floor(WIDTH / 4) - Math.floor(b.block[b.direction].length / 2),
            y: -b.block[b.direction].length,
            blockParent: b.block,
            direction: b.direction,
            style: this.data.style,
            block: b.block[b.direction]
        };

        this.data.number++;
        this.data.fraction--;
        if (this.data.fraction < 0) {
            this.gameOver();
        }

        return block;
    };

    User.prototype.handle = function(evt) {
        var actions = [];

        if (evt.type === 'touchstart') {
            this.handleBegin = {};
            this.handleBegin.x = evt.changedTouches[0].clientX;
            this.handleBegin.y = evt.changedTouches[0].clientY;
        } else if (evt.type === 'touchend' && this.handleBegin) {
            var width = evt.changedTouches[0].clientX - this.handleBegin.x;
            var height = evt.changedTouches[0].clientY - this.handleBegin.y;
            if (width > this.actionWidth) {
                this.action('right');
            } else if (width < -this.actionWidth) {
                this.action('left');
            }
            if (height > this.actionHeight) {
                this.action('bottom');
            } else if (height < -this.actionHeight) {
                this.action('top');
            }
            this.handleBegin = false;
        }
    };

    User.prototype.action = function(action) {
        switch (action) {
            case 'left':
                this.block.checkRepeat(this.myBlock, false);
                if (this.block.checkRepeat({
                    x: this.myBlock.x - 1,
                    y: this.myBlock.y,
                    block: this.myBlock.block,
                }) === false) {
                    this.myBlock.x--;
                }
                this.block.checkRepeat(this.myBlock, true);
                break;
            case 'right':
                this.block.checkRepeat(this.myBlock, false);
                if (this.block.checkRepeat({
                    x: this.myBlock.x + 1,
                    y: this.myBlock.y,
                    block: this.myBlock.block,
                }) === false) {
                    this.myBlock.x++;
                }
                this.block.checkRepeat(this.myBlock, true);
                break;
            case 'bottom':
                this.block.checkRepeat(this.myBlock, false);
                if (this.block.checkRepeat({
                    x: this.myBlock.x,
                    y: this.myBlock.y + 1,
                    block: this.myBlock.block,
                }) === false) {
                    this.myBlock.y++;
                    this.block.checkRepeat(this.myBlock, true);
                } else {
                    if(this.myBlock.y === -this.myBlock.block.length){
                        this.gameOver();
                    }else{
                        this.block.checkRepeat(this.myBlock, true);
                        var that = this;
                        this.updateLock = 'delete';
                        this.block.checkDelete(function(line) {
                            if (line > 0) {
                                that.data.line += line;
                                that.data.fraction += Math.pow(2, line);
                            }
                            that.myBlock = that.getBlock();
                            that.updateLock = false;
                        });
                    }
                }
                break;
            case 'top':
                this.block.checkRepeat(this.myBlock, false);
                if (this.block.checkRepeat({
                    x: this.myBlock.x,
                    y: this.myBlock.y,
                    block: this.myBlock.blockParent[(this.myBlock.direction + 1) % 4],
                }) === false) {
                    this.myBlock.direction = (++this.myBlock.direction) % 4;
                    this.myBlock.block = this.myBlock.blockParent[this.myBlock.direction];
                }
                this.block.checkRepeat(this.myBlock, true);
                break;
        }
    };

    User.prototype.gameOver = function() {
        this.isGameOver = true;
    };

    User.prototype.update = function(time) {
        var timeGo = time - (this.lastTime || 0);
        if (!this.isGameOver && timeGo > SPEED_MIN) {
            this.lastTime = time;
            if (this.updateLock === false) {
                this.action('bottom');
            }
        }
    };
}(window, document);